﻿using CoreCms.Net.Identity.Authorization.Handlers;
using CoreCms.Net.Identity.Authorization.Requirements;
using CoreCms.Net.IServices;

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Silky.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CoreCms.Net.Web.Admin.Authorization;

/// <summary>
/// Admin权限处理
/// </summary>
public class AdminAuthorizationPermissionHandler : SilkyAuthorizationPermissionHandlerBase
{
    /// <summary>
    /// 验证方案提供对象
    /// </summary>
    public IAuthenticationSchemeProvider Schemes { get; set; }

    private readonly ISysRoleMenuServices _sysRoleMenuServices;
    private readonly IHttpContextAccessor _accessor;

    /// 构造函数注入
    /// </summary>
    /// <param name="schemes"></param>
    /// <param name="navigationRepository"></param>
    /// <param name="accessor"></param>
    public AdminAuthorizationPermissionHandler(IAuthenticationSchemeProvider schemes
        , ISysRoleMenuServices sysRoleMenuServices
        , IHttpContextAccessor accessor)
    {
        _accessor = accessor;
        Schemes = schemes;
        _sysRoleMenuServices = sysRoleMenuServices;
    }

    protected override async Task<bool> PolicyPipelineAsync(AuthorizationHandlerContext context, HttpContext httpContext, PermissionRequirement requirement)
    {
        //请求Url
        if (httpContext != null)
        {
            //判断请求是否停止
            var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
            foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
            {
                if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler
                    && await handler.HandleRequestAsync())
                {
                    return false;
                }
            }
            //判断请求是否拥有凭据，即有没有登录
            var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
            if (defaultAuthenticate != null)
            {
                var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
                //result?.Principal不为空即登录成功
                if (result?.Principal != null)
                {
                    return await CheckPermissionAsync(httpContext);
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
            //判断没有登录时，是否访问登录的url,并且是Post请求，并且是form表单提交类型，否则为失败
            //if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasJsonContentType()))
            //{
            //    context.Fail();
            //    return;
            //}
        }
        return true;
    }

    /// <summary>
    /// 业务权限判断
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public async Task<bool> CheckPermissionAsync(HttpContext httpContext)
    {
        var questUrl = httpContext.Request.Path.Value.ToLower();
        // 获取当前用户的角色信息
        var currentUserRoles = new List<string>();
        // jwt
        currentUserRoles = (from item in httpContext.User.Claims
                            where item.Type == ClaimTypes.Role
                            select item.Value).ToList();

        //获取角色菜单数据(cache
        var data = await _sysRoleMenuServices.RoleModuleMaps();
        var list = new List<PermissionItem>();
        list = (from item in data
                orderby item.id
                select new PermissionItem
                {
                    Url = item.menu?.component,
                    RouteUrl = item.menu?.path,
                    Authority = item.menu?.authority,
                    Role = item.role?.roleCode,
                }).ToList();

        var isMatchRole = false;
        var permisssionRoles = list.Where(w => currentUserRoles.Contains(w.Role));
        foreach (var item in permisssionRoles)
        {
            try
            {
                //权限中是否存在请求的url
                if (Regex.Match(questUrl, item.Url.ObjectToString().ToLower()).Value == questUrl)
                {
                    isMatchRole = true;
                    break;
                }
            }
            catch (Exception)
            {
                // ignored
            }
        }

        //验证权限
        if (currentUserRoles.Count <= 0 || !isMatchRole)
        {
            return false;
        }
        var isExp = false;

        // jwt
        isExp = (httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null
            && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now;
        return isExp ? true : false;
    }
}